package kitty.main;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.TimeZone;

import kitty.main.db.DataManager;
import kitty.main.db.HighScore;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.example.kittyvszombie.R;

public class MainView extends SurfaceView implements SurfaceHolder.Callback {

	private static final String TAG = MainView.class.getSimpleName();
	// classes
	private MainThread thread;
	private String avgFps;
	private Enemy enemy;
	// variables
	private float dp;
	private boolean showTP;
	private long tPTimer;
	private Bitmap backgroundhearts, logo, levelselect, background,
			villagelevel, snowlevel, touchPrompt, diffBit, deathscreen;
	Bitmap[] enemyImages = new Bitmap[28];
	private MediaPlayer themesong, villagesong, snowsong;
	private Interface interf;
	private int selectedLevel;
	private int rows = 3;
	private int columns = 9;
	private long startTime;
	private Kitty[][] kittyGrid = new Kitty[rows][columns];
	private int touchCordY, touchCordX, xSquare, timeSurvived, zombiesKilled,
			starsCollected, screenTouches;
	private int nbrOfStars = 20;
	private char ySquare;
	private boolean painted = false;
	private boolean dbOpsDone = false;
	private boolean [] enemyOnRow = new boolean[3];
	//DJ ROBIN
	private SoundPool sounds;
	private int soundCat,soundSwap, soundGameOver, soundCuteCat, soundStar, soundThrow, soundGrid, soundHit, soundZombieDie1, soundZombieDie2, soundZombieAppear1, soundZombieAppear2;
	
	
	DataManager dataMng;
	ArrayList<HighScore> highScores;
	
	private ArrayList<Projectile> projectiles = new ArrayList<Projectile>();

	public ArrayList<Projectile> getProjectiles() {
		return projectiles;
	}

	public enum GameState {
		STARTSCREEN, LEVELSELECT, GAMEPLAY, GAMEOVER
	}

	public enum Difficulty {
		MOM, BEGINNER, EASY, MEDIUM, HARD, EXTREME, IMPOSSIBLE
	}

	Difficulty difficulty;
	GameState gameState;
	private float spawnEnemyTimer;
	private int enemyCounter = 0;
	private ArrayList<Enemy> enemies = new ArrayList<Enemy>();
	private ArrayList<Star> stars = new ArrayList<Star>();
	private float enemySpeed;
	private int enemyHp;
	private float enemySpawnTime;

	public MainView(Context context) {
		super(context);
		getHolder().addCallback(this);
		thread = new MainThread(getHolder(), this);
		dp = getResources().getDisplayMetrics().density;
		tPTimer = System.currentTimeMillis();
		gameState = GameState.STARTSCREEN;
		difficulty = Difficulty.MOM;
		dataMng = new DataManager(getContext());
		try {
			dataMng.open();
			highScores = dataMng.getAllHighScores();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		dataMng.close();
		
		loadResources();

		loadSounds(context);
		
		
		
		interf = new Interface(this);
	}

	private void loadSounds(Context context) {
		// music
		themesong = MediaPlayer.create(getContext(), R.raw.themesong);
		villagesong =  MediaPlayer.create(getContext(), R.raw.villagetheme);
		snowsong =  MediaPlayer.create(getContext(), R.raw.snowtheme);
		
		//SOUNDROBIN
		//DJ ROBIN
		sounds = new SoundPool(10, AudioManager.STREAM_MUSIC,0);
		soundCat = sounds.load(context, R.raw.cat, 1);
		soundCuteCat = sounds.load(context, R.raw.cutecat, 1);
		soundThrow = sounds.load(context, R.raw.throwp, 1);
		soundHit = sounds.load(context, R.raw.prhit, 1);
		soundGrid = sounds.load(context, R.raw.placing, 1);
		soundStar = sounds.load(context, R.raw.star, 1);	
		soundZombieDie1 = sounds.load(context, R.raw.zombiedie, 1);
		soundZombieDie2 = sounds.load(context, R.raw.zombiedie2, 1);
		soundZombieAppear1 = sounds.load(context, R.raw.zombie, 1);
		soundZombieAppear2 = sounds.load(context, R.raw.zombie2, 1);
		soundSwap = sounds.load(context, R.raw.swap, 1);
		soundGameOver = sounds.load(context, R.raw.gameover, 1);
	}

	public void render(Canvas canvas) {
		// RITAAAA

		// visa alltid en bakgrund underst
		canvas.drawBitmap(background, 0, 0, null);

		if (gameState == GameState.STARTSCREEN) {

			canvas.drawBitmap(logo, 0, 0, null);

			if (showTP) {
				canvas.drawBitmap(touchPrompt, 600, 200, null);
			}
		}

		else if (gameState == GameState.LEVELSELECT) {
			canvas.drawBitmap(levelselect, 45, 100, null);
		}

		else if (gameState == GameState.GAMEPLAY) {

			interf.render(canvas);
			drawKitties(canvas);
			drawEnemies(canvas);
			checkCollision();

			drawProjectiles(canvas);
			drawStars(canvas);
			decideDifficulty(canvas);
		}

		else if (gameState == GameState.GAMEOVER) {
			canvas.drawBitmap(deathscreen, 0, 0, null);
			Paint paint = new Paint();
			paint.setFakeBoldText(true);
			paint.setColor(Color.BLACK);
			paint.setTextSize(30);
			int score = zombiesKilled*10+timeSurvived*5+starsCollected*10;

			canvas.drawText("Score: "+score, 450, 400, paint);
			canvas.drawText("Time survived: " + timeSurvived, 450, 450, paint);
			canvas.drawText("Zombies killed: " + zombiesKilled, 450, 500, paint);
			canvas.drawText("Stars collected: " + starsCollected, 450, 550,
					paint);
			canvas.drawText("Nr of touches: " + screenTouches, 450,
					600, paint);
			TimeZone tz = TimeZone.getTimeZone("Europe/Stockholm");
			final Calendar c = Calendar.getInstance();
			c.setTimeZone(tz);
			int month;
			if(dbOpsDone==false) {
				DataManager dataMng = new DataManager(this.getContext());
				HighScore thisHighScore = new HighScore();
				thisHighScore.setScore(score);
				thisHighScore.setDatetime(c.getTimeInMillis());
				try {
					dataMng.open();
					dataMng.insertHighScore(thisHighScore);
					highScores = dataMng.getAllHighScores();

				} catch (java.sql.SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				dataMng.close();
				dbOpsDone=true;
			}
			
			for(int i = 0; i<highScores.size(); i++) {
				HighScore highScore;
				highScore = highScores.get(i);
				c.setTimeInMillis(highScore.getDatetime());
				month = c.get(Calendar.MONTH);
				month += 1;
				canvas.drawText(highScore.getScore() +"  " + 
						c.get(Calendar.YEAR)+"-"+month+"-"+c.get(Calendar.DAY_OF_MONTH),
						850, 400+i*50, paint);
				if(i==5) {
					i=highScores.size();
				}
			}
		}
		//displayFps(canvas, avgFps);
	}

	private void drawProjectiles(Canvas canvas) {
		for(int i = 0; i < projectiles.size();i++){
			projectiles.get(i).render(canvas);
			if(projectiles.get(i).getRemoved()){
				projectiles.remove(i);
			}
		}
	}

	private void drawStars(Canvas canvas) {
		for (int i = 0; i < stars.size(); i++) {
			stars.get(i).render(canvas);

			if (stars.get(i).getRemove()) {
				stars.remove(i);
			}
		}
	}

	private void drawKitties(Canvas canvas) {
		for (int i = 0; i < rows; i++) {
			for (int x = 0; x < columns; x++) {
				if (kittyGrid[i][x] != null) {
					kittyGrid[i][x].render(canvas);
				}
			}
		}
	}

	public void update() {
		// UPPDATERA

		if (gameState == GameState.STARTSCREEN) {

			if (tPTimer <= System.currentTimeMillis() - 1000) { // En timer utan
																// delta kommer
																// bugga som en
																// galning
																// s�fort man
																// tabbar ur
																// spelet.
				tPTimer = System.currentTimeMillis(); // Sant, dock �r det bara
														// en flashande text p�
														// startsk�rmen s� det
														// g�r inget.
				showTP = !showTP;
			}

			// testa starta musik
			 if(this.hasWindowFocus() && !themesong.isPlaying()){
			 themesong.start(); }
		}

		else if (gameState == GameState.GAMEPLAY) {
			interf.update();
			checkEnemiesOnRow();
		}

	}

	public void createEnemies() {
		checkDifficulty();
		spawnEnemyTimer += thread.getDelta();
		if (spawnEnemyTimer >= enemySpawnTime) {
			enemies.add(new Enemy(enemyImages, enemySpeed, enemyHp, this));
			enemyCounter++;
			spawnEnemyTimer -= enemySpawnTime;
		}
	}
	

	public void checkCollision() {
		for (int j = 0; j < enemies.size(); j++) {
			Rect e = new Rect(enemies.get(j).getBounds());
			for (int i = 0; i < rows; i++) {
				for (int x = 0; x < columns; x++) {
					if (kittyGrid[i][x] != null && !kittyGrid[i][x].isDead()) {
						Rect k = kittyGrid[i][x].getBounds();
						if (k.intersect(e)
								&& enemies.get(j).getId() == kittyGrid[i][x]
										.getRow()) {
							kittyGrid[i][x].kill(); // att g�ra n�r zombie
													// krockar med katt.
						}
					}
				}
			}
		}
	}

	public void decideDifficulty(Canvas canvas) {
		switch (enemyCounter) { // balansera
		case 10:
			difficulty = Difficulty.BEGINNER;
			difficultyText(canvas);
			break;
		case 20:
			difficulty = Difficulty.EASY;
			difficultyText(canvas);
			break;
		case 30:
			difficulty = Difficulty.MEDIUM;
			difficultyText(canvas);
			break;
		case 40:
			difficulty = Difficulty.HARD;
			difficultyText(canvas);
			break;
		case 50:
			difficulty = Difficulty.EXTREME;
			difficultyText(canvas);
			break;
		case 60:
			difficulty = Difficulty.IMPOSSIBLE;
			difficultyText(canvas);
			break;
		}
	}

	public void checkDifficulty() {
		switch (difficulty) { // balansera
		case MOM:
			enemySpawnTime = 10.0f;
			enemySpeed = 20.f;
			enemyHp = 5;
			break;
		case BEGINNER:
			enemySpawnTime = 6.0f;
			enemySpeed = 30.f;
			enemyHp = 7;
			break;
		case EASY:
			enemySpawnTime = 5.0f;
			enemySpeed = 40.f;
			enemyHp = 12;
			break;
		case MEDIUM:
			enemySpawnTime = 4.0f;
			enemySpeed = 50.f;
			enemyHp = 15;
			break;
		case HARD:
			enemySpawnTime = 4.0f;
			enemySpeed = 60.f;
			enemyHp = 17;
			break;
		case EXTREME:
			enemySpawnTime = 3.0f;
			enemySpeed = 20.f;
			enemyHp = 20;
			break;
		case IMPOSSIBLE:
			enemySpawnTime = 2.0f;
			enemySpeed = 20.f;
			enemyHp = 30;
			break;
		}
	}

	public void drawEnemies(Canvas canvas) {
		createEnemies();
		for (int i = 0; i < enemies.size(); i++) {
			enemies.get(i).render(canvas);
			if(enemies.get(i).getRemove()){
				enemies.remove(i);
			}
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		touchCordY = (int) event.getY();
		touchCordX = (int) event.getX();
		//DJ ROBIN
		//sounds.play(soundCat, 1.0f, 1.0f, 0, 0, 1.5f);

		if (gameState == GameState.STARTSCREEN) {
			gameState = GameState.LEVELSELECT;
			background = backgroundhearts;
		}

		else if (gameState == GameState.LEVELSELECT) {
			if (touchCordX < this.getWidth() / 2) {
				background = villagelevel;
				villagesong.start();
				villagesong.setLooping(true);
				selectedLevel = 1;
				gameState = GameState.GAMEPLAY;
			} else if (touchCordX > this.getWidth() / 2) {
				background = snowlevel;
				snowsong.start();
				snowsong.setLooping(true);
				selectedLevel = 2;
				
				gameState = GameState.GAMEPLAY;
			}
			themesong.stop();
			startTime = System.currentTimeMillis();
		}

		else if (gameState == GameState.GAMEPLAY) {
			interf.onTouchEvent(event);
			checkStarsTouch();
		}
		else if (gameState == GameState.GAMEOVER) {
			if(touchCordY > 600){
				restart();
			}
		}
		
		screenTouches++;

		return super.onTouchEvent(event);
	}

	private void checkStarsTouch() {
		for (int i = 0; i < stars.size(); i++) {
			if (touchCordX > stars.get(i).getX()
					&& touchCordX < stars.get(i).getX() + 100
					&& touchCordY > stars.get(i).getY()
					&& touchCordY < stars.get(i).getY() + 100) {
				stars.get(i).collect();
			}
		}
	}
	
	public void addCollectedStar(){
		starsCollected++;
	}


	public void setAvgFps(String avgFps) {
		this.avgFps = avgFps;
	}

	public float getDp() {
		return dp;
	}
	
	public boolean isEnemyOnRow(int row) {
		return enemyOnRow[row];
	}
	
	public void checkEnemiesOnRow(){
		enemyOnRow[0] = false;
		enemyOnRow[1] = false;
		enemyOnRow[2] = false;
		for(int i = 0; i < enemies.size(); i++){
			switch (enemies.get(i).getId()){
			case 0:
				enemyOnRow[0] = true;
				break;
			case 1:
				enemyOnRow[1] = true;
				break;
			case 2:
				enemyOnRow[2] = true;
				break;
			}
		}		
	}

	private void difficultyText(Canvas canvas) {
		canvas.drawBitmap(diffBit, this.getWidth() / 9, this.getHeight() / 2,
				null);
	}

	private void displayFps(Canvas canvas, String fps) {
		if (canvas != null && fps != null) {
			Paint paint = new Paint();
			paint.setARGB(255, 255, 255, 255);
			canvas.drawText(fps, this.getWidth() - 50 * dp, 20 * dp, paint);
		}
	}

	public ArrayList<Enemy> getEnemies() {
		return enemies;
	}

	public void onWindowFocusChanged(boolean hasWindowFocus) {
		
		if(gameState == GameState.STARTSCREEN || gameState == GameState.LEVELSELECT){
			themesong.start();
		}
		
		else if(gameState == GameState.GAMEPLAY && selectedLevel == 1){
			villagesong.start();
		}
		else if(gameState == GameState.GAMEPLAY && selectedLevel == 2){
			snowsong.start();
		}
		
		if (!hasWindowFocus) {
			if(themesong.isPlaying())
			themesong.pause();
			if(villagesong.isPlaying())
				villagesong.pause();
			if(snowsong.isPlaying())
				snowsong.pause();
			thread.pause();
		}

	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		// SMACK A BITCH
		// Watch your language, mister!
		
		
			
		
		backgroundhearts = Bitmap.createScaledBitmap(backgroundhearts, width,
				height, true);
		snowlevel = Bitmap.createScaledBitmap(snowlevel, width, height, true);
		villagelevel = Bitmap.createScaledBitmap(villagelevel, width, height,
				true);
		deathscreen  = Bitmap.createScaledBitmap(deathscreen, width, height,
				true);
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		if (thread.getState() == Thread.State.TERMINATED) {
			thread = new MainThread(getHolder(), this);
			thread.setRunning(true);
			thread.start();
		} else {
			thread.setRunning(true);
			thread.start();
		}
	}
	
	public void restart(){
		interf.restart();
		gameState = GameState.STARTSCREEN;
		starsCollected = 0;
		zombiesKilled = 0;
		screenTouches = 0;
		nbrOfStars = 20;
		difficulty = Difficulty.MOM;
		dbOpsDone = false;
		enemyCounter = 0;
		
		//clear kittyGrid
		for (int i = 0; i < rows; i++) {
			for (int x = 0; x < columns; x++) {
				if(kittyGrid[i][x] != null){
					kittyGrid[i][x] = null;
				}
			}
		}
		
		stars.clear();
		projectiles.clear();
		if(selectedLevel == 1){
			background = snowlevel;
		}
		else{
			background = villagelevel;
		}
		
		enemies.clear();
		themesong.prepareAsync();
		themesong.start();
		themesong.setLooping(true);
		tPTimer = System.currentTimeMillis();
		
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		Log.d(TAG, "Surface is being destroyed");
		thread.pause();
		boolean retry = true;
		thread.setRunning(false);
		while (retry) {
			try {
				thread.join();
				retry = false;
			} catch (InterruptedException e) {
			}
		}
		Log.d(TAG, "Thread was shut down cleanly");

	}

	public Kitty[][] getKittyGrid() {
		return kittyGrid;
	}

	public double getDelta() {
		return thread.getDelta();
	}

	public ArrayList getStars() {
		return stars;
	}

	public void addStars(int value) {
		nbrOfStars += value;
	}

	public int getNumberOfStars() {
		return nbrOfStars;
	}

	public int getElapsedTime() {
		long timeElapsedInSec = (System.currentTimeMillis() - startTime) / 1000;

		return (int) timeElapsedInSec;
	}

	public void endGame() {
		playGameOverSound();
		if(villagesong.isPlaying()){
			villagesong.stop();
		}
		
		else if (snowsong.isPlaying()){
			snowsong.stop();
		}
		gameState = GameState.GAMEOVER;
		timeSurvived = this.getElapsedTime();
	}

	public void addZombieKilled() {
		zombiesKilled++;
	}

	private void loadResources() {
		// images
		backgroundhearts = BitmapFactory.decodeResource(getResources(),
				R.drawable.background_hearts);

		logo = BitmapFactory.decodeResource(getResources(), R.drawable.logo);

		levelselect = BitmapFactory.decodeResource(getResources(),
				R.drawable.chooselevel);

		villagelevel = BitmapFactory.decodeResource(getResources(),
				R.drawable.background);

		snowlevel = BitmapFactory.decodeResource(getResources(),
				R.drawable.background2);

		touchPrompt = BitmapFactory.decodeResource(getResources(),
				R.drawable.touchanywhere);

		diffBit = BitmapFactory.decodeResource(getResources(),
				R.drawable.difficulty);
		
		deathscreen  = BitmapFactory.decodeResource(getResources(),
				R.drawable.deathscreen);

		// load enemyImages
		enemyImages[0] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z0);
		enemyImages[1] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z1);
		enemyImages[2] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z2);
		enemyImages[3] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z3);
		enemyImages[4] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z4);
		enemyImages[5] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z5);
		enemyImages[6] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z6);
		enemyImages[7] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z7);
		enemyImages[8] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z8);
		enemyImages[9] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z9);
		enemyImages[10] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z10);
		enemyImages[11] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z11);
		enemyImages[12] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z12);
		enemyImages[13] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z13);
		enemyImages[14] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z14);
		enemyImages[15] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z15);
		enemyImages[16] = BitmapFactory.decodeResource(getResources(),
				R.drawable.z16);
		enemyImages[17] = BitmapFactory.decodeResource(getResources(),
				R.drawable.zd0);
		enemyImages[18] = BitmapFactory.decodeResource(getResources(),
				R.drawable.zd1);
		enemyImages[19] = BitmapFactory.decodeResource(getResources(),
				R.drawable.zd2);
		enemyImages[20] = BitmapFactory.decodeResource(getResources(),
				R.drawable.zd3);
		enemyImages[21] = BitmapFactory.decodeResource(getResources(),
				R.drawable.zd4);
		enemyImages[22] = BitmapFactory.decodeResource(getResources(),
				R.drawable.zd5);
		enemyImages[23] = BitmapFactory.decodeResource(getResources(),
				R.drawable.zd6);
		enemyImages[24] = BitmapFactory.decodeResource(getResources(),
				R.drawable.zd7);
		enemyImages[25] = BitmapFactory.decodeResource(getResources(),
				R.drawable.zd8);
		enemyImages[26] = BitmapFactory.decodeResource(getResources(),
				R.drawable.zd9);
		enemyImages[27] = BitmapFactory.decodeResource(getResources(),
				R.drawable.zd10);
		background = backgroundhearts;
	}

	public void playGridSound(){
		sounds.play(soundGrid, 1.0f, 1.0f, 0, 0, 1.0f);
	}
	
	public void playGameOverSound(){
		sounds.play(soundGameOver, 1.0f, 1.0f, 0, 0, 1.0f);
	}
	
	public void playThrowSound(){
		sounds.play(soundThrow, 1.0f, 1.0f, 0, 0, 1.0f);
	}
	
	public void playHitSound(){
		sounds.play(soundHit, 1.0f, 1.0f, 0, 0, 1.0f);
	}
	
	public void playCatSound(){
		sounds.play(soundCat, 1.0f, 1.0f, 0, 0, 1.0f);
	}
	
	public void playCuteCatSound(){
		sounds.play(soundCuteCat, 1.0f, 1.0f, 0, 0, 1.0f);
	}
	
	public void playStarSound(){
		sounds.play(soundStar, 1.0f, 1.0f, 0, 0, 1.0f);
	}
	
	public void playZombieDie1(){
		sounds.play(soundZombieDie1, 1.0f, 1.0f, 0, 0, 1.0f);
	}
	
	public void playZombieDie2(){
		sounds.play(soundZombieDie2, 1.0f, 1.0f, 0, 0, 1.0f);
	}

	public void playZombieAppear1(){
		sounds.play(soundZombieAppear1, 1.0f, 1.0f, 0, 0, 1.0f);
	}
	
	public void playZombieAppear2(){
		sounds.play(soundZombieAppear2, 1.0f, 1.0f, 0, 0, 1.0f);
	}
	
	public void playSwapSound(){
		sounds.play(soundSwap, 1.0f, 1.0f, 0, 0, 1.0f);
	}
}

